﻿using System;
using System.Collections.Generic;
using Cms.Application.Admin.Presenters;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Cms.Domain;
using Cms.Application.Admin.Views;
using Moq;

namespace Cms.Tests.Unit.Application.Admin.Presenters
{
    [TestClass]
    public class AdministratorGroupsPresenterTests : BasePresenterTests
    {
        private Administrator _admin;
        private Mock<IAdministratorGroupsView> _viewMock;
        private AdministratorGroup _admins;
        private AdministratorGroup _powerUsers;
        private IList<AdministratorGroup> _groups;
        
        private void GeneralPrepare()
        {
            _admin = new Administrator
            {
                DefaultSystemLocale = "en-US",
                Email = "test@fredium.com",
                Firstname = "Charles",
                Lastname = "Bronson",
                Password = "dontmess",
                Username = "daman",
                DateFormat = "yyyy-MM-dd",
                TimeFormat = "HH:mm",
                Created = new DateTime(2010, 03, 19),
            };
            AdministratorGroup group = new AdministratorGroup { ID = 1 };
            group.Administrators.Add(_admin);
            _admin.Group = group;
            InitRepositoryFactoryMock();
            AdministratorRepositoryMock.Setup(a => a.GetAdministrator(1)).Returns(_admin);
            _viewMock = new Mock<IAdministratorGroupsView>();
            _viewMock.SetupAllProperties();
            _viewMock.Setup(v => v.AdministratorID).Returns(1);
            _viewMock.Setup(v => v.Localization).Returns("en-US");
            _viewMock.Setup(v => v.ContextTranslationFile).Returns("Admin/Translations/AdministratorGroups.xml");
        }
        
        [TestMethod]
        public void Initialize_SetGroupsIsCalled()
        {
            GeneralPrepare();
            AdministratorGroupsPresenter presenter = new AdministratorGroupsPresenter(_viewMock.Object, FactoryMock.Object);
            presenter.Initialize();
            _viewMock.Verify(o => o.SetGroups(It.IsAny<IList<AdministratorGroup>>()));
        }
        
        private void PrepareGroups()
        {
            _admins = new AdministratorGroup() { ID = 1, Name = "Administrators" };
            _powerUsers = new AdministratorGroup() { ID = 2, Name = "Power Users" };
            _groups = new List<AdministratorGroup> {_admins, _powerUsers};
            AdministratorRepositoryMock.Setup(a => a.GetGroups()).Returns(_groups);
            AdministratorRepositoryMock.Setup(a => a.GetGroup(1)).Returns(_admins);
            AdministratorRepositoryMock.Setup(a => a.GetGroup(2)).Returns(_powerUsers);
        }
        
        [TestMethod]
        public void SetGroups_ReturnTwoGroups()
        {
            GeneralPrepare();
            PrepareGroups();
            AdministratorGroupsPresenter presenter = new AdministratorGroupsPresenter(_viewMock.Object, FactoryMock.Object);
            presenter.SetGroups();
            _viewMock.Verify(o => o.SetGroups(_groups));
        }
        
        [TestMethod]
        public void DeleteGroup_GroupIsEmpty_Success()
        {
            GeneralPrepare();
            PrepareGroups();
            AdministratorGroupsPresenter presenter = new AdministratorGroupsPresenter(_viewMock.Object, FactoryMock.Object);
            presenter.DeleteGroup(2); // Power users, empty group
            AdministratorRepositoryMock.Verify(o => o.DeleteGroup(2));
        }
        
        [TestMethod]
        public void DeleteGroup_GroupIsNotEmptyReplacementsAvailable_DisplayReplacementDialog()
        {
            GeneralPrepare();
            PrepareGroups();
            Administrator userA = new Administrator { Group = _powerUsers };
            _powerUsers.Administrators.Add(userA);
            AdministratorGroupsPresenter presenter = new AdministratorGroupsPresenter(_viewMock.Object, FactoryMock.Object);
            presenter.DeleteGroup(2); // Power users, contains one user
            _viewMock.Verify(o => o.SetReplacements(It.IsAny<IList<AdministratorGroup>>(), _powerUsers.Name));
        }
        
        [TestMethod]
        public void DeleteGroup_GroupIsNotEmptyNoReplacementsExists_DisplayError()
        {
            // This cannot happen since the group Administrators cannot be deleted
        }
        
        [TestMethod]
        public void ReplaceAndDeleteGroup_GroupIsNotEmpty_AdministratorsAreMovedToTheReplacementGroupAndOriginalGroupIsDeleted()
        {
            GeneralPrepare();
            PrepareGroups();
            Administrator userA = new Administrator { Group = _powerUsers };
            _powerUsers.Administrators.Add(userA);
            AdministratorGroupsPresenter presenter = new AdministratorGroupsPresenter(_viewMock.Object, FactoryMock.Object);
            presenter.ReplaceAndDeleteGroup(2, 1); // Power users, contains one user
            Assert.IsTrue(_admins.Administrators.Contains(userA));
            Assert.IsFalse(_powerUsers.Administrators.Contains(userA));
            Assert.AreSame(_admins, userA.Group);
            AdministratorRepositoryMock.Verify(o => o.DeleteGroup(2));
        }
    }
}
